(function($) {
    $.fn.duplicate = function(options){
        var opts = $.extend({}, $.fn.duplicate.defaults, options);
        return this.each(function() {
            $this = $(this);
            var id = $this.attr('id');
            $.fn.duplicate.settings[id] = $.meta ? $.extend({}, opts, $this.data()) : opts;
        });
    };
    
    $.fn.duplicate.add = function(id, current_item) {
        var settings = $.fn.duplicate.settings[id];
        var item = $(current_item).clone();
        //clean data
        $('input, textarea', item).each(function(){
            $(this).val('');
        });
        var index = $.fn.duplicate.get_index(id, current_item)+1;
        item = $.fn.duplicate.update_index(id, item, index);
        
        //callback
        if(settings.beforeAdd != undefined)
            settings.beforeAdd(id, item);
        
        //update order
        $(current_item).nextAll('.'+settings.item_class).each(function(i){
            $.fn.duplicate.update_index(id, $(this), index+i+1);
        });
        
        $(current_item).after(item);
        //callback
        if(settings.afterAdd != undefined)
            settings.afterAdd(id, item);
            
        if (settings.focus_item != false)
            $(settings.focus_item, item).focus();
    }
    
    $.fn.duplicate.remove = function(id, item) {
        var settings = $.fn.duplicate.settings[id];
        var index = $.fn.duplicate.get_index(id, item);
        
        //callback
        if(settings.beforeRemove != undefined)
            settings.beforeRemove(id, item);
        
        //update order
        $(item).nextAll('.'+settings.item_class).each(function(i){
            $.fn.duplicate.update_index(id, $(this), index+i);
        });
        
        item.remove();
        //callback
        if(settings.afterRemove != undefined)
            settings.afterRemove(id, item);
    };
    
    $.fn.duplicate.get_index = function(id, current_item) {
        var settings = $.fn.duplicate.settings[id];
        return parseInt($(current_item).attr('id').replace(settings.item_id_prefix, ''));
    };
    
    $.fn.duplicate.update_index = function(id, item, index) {
        var settings = $.fn.duplicate.settings[id];
        $.each($('input, textarea, label', item), function(){
            var id = $(this).attr('id');
            if (id != undefined) {
                id = id.replace(/_\d+_/g, '_'+index+'_');
                $(this).attr('id', id);
            }
            var for_id = $(this).attr('for');
            if (for_id != undefined) {
                for_id = for_id.replace(/_\d+_/g, '_'+index+'_');
                $(this).attr('for', for_id);
            }
            var name = $(this).attr('name');
            if (name != undefined) {
                name = name.replace(/\[\d+\]/g, '['+index+']');
                $(this).attr('name', name);
            }
        });
        item.attr('id', settings.item_id_prefix+index);
        return item;
    }

    $.fn.duplicate.defaults = {
        item_id_prefix: '',
        item_class : '',
        focus_item: 'input:first'
    };
    
    $.fn.duplicate.settings = {};
})(jQuery);